﻿using QDAS;
using QDasConverter.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WindGoes6.Database;

namespace QDasConverter.Core
{
    /// <summary>
    /// 沈寒梅的转换器。
    /// </summary>
    public class C2021T20_ComaAtlas : ConvertBase
    {
        DateTime startDate = new DateTime(2000, 1, 1);
        int transCount = 50;

        Dictionary<string, string[]> programParamters = new Dictionary<string, string[]>();
        Dictionary<string, string> rsdic = new Dictionary<string, string>();

        List<QFile> qfs = new List<QFile>();
        string k1303 = "";
        string k1042 = "";
        string k1091 = "";

        // ASSY_UNKNOW
        Dictionary<string, string> K1002s = new Dictionary<string, string>();
        Dictionary<string, string> K1042s = new Dictionary<string, string>();

        public C2021T20_ComaAtlas()
        {
            DisplayName = "柯马ATLAS转换器";
            DisplayName = "Atlas 转换器";
            Version = "alpha Released Date: 2021/10/05 Inner Name: C2021T01_Atlas";
            Version = "beta1 Released Date: 2021/11/09 Inner Name: C2021T01_Atlas";
            Version = "beta1 Released Date: 2021/11/09 Inner Name: C2021T01_Atlas";
            Version = "beta0.1.0 Released Date: 2021/11/17 Inner Name: C2021T01_Atlas";

            LoadDictionary(K1002s, "K1002.ini");
            LoadDictionary(K1042s, "K1042.ini");
        }

        private void LoadDictionary(Dictionary<string, string> dic, string inifile)
        {
            inifile = Path.GetFullPath(inifile);
            if (!File.Exists(inifile))
                return;

            foreach (var line in File.ReadAllLines(inifile))
            {
                if (line == null || !line.Contains("="))
                    continue;

                string[] keys = line.Split('=')[1].Split(',');
                string value = line.Split('=')[0];
                foreach (string key in keys)
                    if (!dic.Keys.Contains(key))
                        dic.Add(key, value);
            }
        }


        private bool needTrans()
        {
            try { LastResID = int.Parse(ia.ReadValue("StartTimeID")); } catch { LastResID = 0; }
            try { startDate = DateTime.Parse(ia.ReadValue("StartTime")); } catch { startDate = new DateTime(2000, 1, 1); }
            // LastResID = 0;

            sm.CommandText = LastResID == 0 ?
                $"select count(ID) from ACDC.Result where ResultDateTime >= '{startDate}'" :
                $"select count(ID) from ACDC.Result where ID > {LastResID}"; 

            return long.TryParse(sm.GetObject()?.ToString(), out long lastIDfromdb) && lastIDfromdb > transCount;
        }

        public override bool OnStart()
        {
            if (DebugMode)
            {
                SqlConnectionString = "Data Source = 117.71.62.132,8092;Initial Catalog = AtlasCopco_ToolsNet_Database_202109150818;User ID = sa; Password = Huaun@2021;";
                sm = new WindGoes6.Database.SQLManager(SqlConnectionString);
            }
            return base.OnStart();
        }

        /// <summary>
        /// 几个问题：
        /// 1）K1002 原来是Unit.Name 现在是什么？
        /// 2）原来通过K1002和K2002进行分组处理，现在修改后还需要吗？
        /// 3）ProgramParameter.ProgramParameterTypeID选取后，是不是只要ResultTighting中的一个值了？
        /// </summary>
        /// <returns></returns>
        public override void OneLoop_Process()
        {
            sm.CommandText = GetSql();
            string[][] data = sm.GetStrings();

            if (data.Length == 0)
                return;

            qfs = new List<QFile>();
            k1303 = ia.ReadString("K1303", "");
            k1042 = ia.ReadString("K1042", "");
            k1091 = ia.ReadString("K1091", "");

            foreach (string[] item in data)
            {
                try
                {
                    processItem(item);
                }
                catch (Exception ex)
                {
                    Common.AddLog(ex.Message, LogType.Error);
                }
            }
            ia.WriteValue("StartTime", data[data.Length - 1][3]);
            ia.WriteValue(Config.LastResID, data[data.Length - 1][0]);

            // Save
            foreach (QFile qf in qfs)
            {
                SaveToDFQ(qf, OutputDirectory, $"{qf[1099]}\\{qf.Tag}_{qf[1099]}_{NowString()}.dfq");
            }
        }


        private void processItem(string[] item)
        {
            /*************************************************************************************************
             * 0.ResultTightening.ResultID              
             * 1.ResultTightening.FinalAngle
             * 2.ResultTightening.FinalTorque
             * 3.Result.ResultDateTime
             * 4.Result.ProgramID
             * 5.ResultIdentifier.Identifier
             * 6.vUnitProgramBolt.UnitName
             * 7.vUnitProgramBolt.BoltName
             * 8.vUnitProgramBolt.SystemType
             * 9.ProgramParameter.ParameterValue
             * 10.ProgramParameter.LimitHigh
             * 11.ProgramParameter.LimitLow
             * 12.Result.PositionID             // 2019-03-15 加入
             * 13.vUnitProgramBolt.ProgramName  // 2019-03-15 加入
             * 14. ResultStep.ResultStepID      // 2019-06-01 追加，LEFT OUTER JOIN
             **************************************************************************************************/
            string resultID = item[0];
            string v1 = item[2]; // FinalTorque
            string v2 = item[1]; // FinalAngle
            DateTime dt = DateTime.Parse(item[3]);
            string programID = item[4];
            string identifier = item[5];
            string unitname = item[6];
            string boltname = item[7];
            string systemtype = item[8];
            string k2101 = item[9];

            string k2110 = item[11];
            string k2111 = item[10];
            //根据吉利要求(上限+下线)/2 llj 20190620
            if (!string.IsNullOrEmpty(k2110) && !string.IsNullOrEmpty(k2111))
            {
                k2101 = ((double.Parse(k2110) + double.Parse(k2111)) / 2.0).ToString("0.00");
            }
            string positionID = item[12];
            string k1087_programName = item[13];
            string k0007 = item[14];


            // each QFile instance has a unique K1001
            string k1001 = GetK1001(identifier);
            string k1002 = K1002s.Keys.Contains(k1001) ? K1002s[k1001] : "ASSY_UNKNOW";
            string k1042 = K1042s.Keys.Contains(k1001) ? K1042s[k1001] : "ASSY_UNKNOW";
            string k1206 = ia.ReadValue("K1206");
            string tag = k1001 + "_" + programID + "_" + positionID;
            QFile qf = qfs.Find(q => (q.Tag as string) == tag);


            if (qf == null)
            {
                qf = new QFile();
                qfs.Add(qf);
                qf[1001] = k1001;
                qf[1002] = k1002;// boltname.ToString().Trim(); 2019/03/19 微信聊天记录 
                qf[1042] = k1042;
                qf[1086] = unitname;
                if (!string.IsNullOrEmpty(k1091))
                    qf[1091] = k1091;
                if (!string.IsNullOrEmpty(k1206))
                    qf[1206] = k1206;
                // qf[1206] = systemtype;
                qf[1303] = k1303;
                qf[1087] = k1087_programName;
                qf.Tag = tag;
            }

            // for test only
            qf[1099] = item[6];

            QCharacteristic qc1 = GetCharacteristic(qf, "BoltName_" + boltname, "FinalTorque");
            qc1[2004] = 0;
            qc1[2016] = 1;
            qc1[2022] = 4;
            qc1[2004] = 0;
            qc1[2005] = 1;
            qc1[2009] = 302;// 根据K2002的名称填写定值：为“FinalTorque”时填写302；为“FinalAngle”时填写320。
            qc1[2022] = 4;
            qc1[2080] = 0;
            qc1[2100] = k2101;
            qc1[2101] = k2101;
            qc1[2110] = k2110;
            qc1[2111] = k2111;
            qc1[2142] = "Nm";
            qc1[8500] = 5;
            qc1[8501] = 0;

            QDataItem qv1 = new QDataItem();
            qv1.SetValue(v1);
            qv1.date = dt;
            if (!string.IsNullOrEmpty(k0007))
                qv1[0007] = k0007;
            qv1[0014] = identifier;
            qc1.data.Add(qv1);


            QCharacteristic qc2 = GetCharacteristic(qf, "BoltName_" + boltname, "FinalAngle");
            qc2[2004] = 0;
            qc2[2016] = 1;
            qc2[2022] = 4;
            qc2[2004] = 0;
            qc2[2005] = 1;
            qc2[2009] = 320;// 根据K2002的名称填写定值：为“FinalTorque”时填写302；为“FinalAngle”时填写320。
            qc2[2022] = 4;
            qc2[2080] = 0;
            qc2[2100] = k2101;
            qc2[2101] = k2101;
            qc2[2110] = k2110;
            qc2[2111] = k2111;
            qc2[2142] = "°";
            qc2[8500] = 5;
            qc2[8501] = 0;

            QDataItem qv2 = new QDataItem();
            qv2.SetValue(v2);   // 2017-6-30 2 -> 1  FinalAngle
            qv2.date = DateTime.Parse(item[3]);
            if (!string.IsNullOrEmpty(k0007))
                qv2[0007] = k0007;
            qv2[0014] = identifier;
            qc2.data.Add(qv2);

        }

        /// <summary>
        /// 2019/01/15，根据《柯马ATLAS转换器开发说明书20190110.docx》中的EXCEL附件的要求修改。
        /// </summary>
        /// <param name="identifier">抽样值。</param>
        /// <returns></returns>
        private string GetK1001(string identifier)
        {
            string k1001 = null;
            string id = identifier.Trim();

            // 1.发动机 提取第一个*之前的内容 不定长, 如 JLH-4G20TD*K1T0000024S*  =>  JLH-4G20TD
            if (identifier.Contains('*'))
            {
                k1001 = identifier.Split('*')[0];
            }

            // 2. 提取以1242或1243开始的前四位并在前面加 550000，如 1242#4D19007#1W000012#T1#  =>  5500001242
            if (id.StartsWith("1242") || id.StartsWith("1243"))
            {
                k1001 = "550000" + id.Substring(0, 4);
            }
            // 第一位固定值为P时，第十二位固定值为#时，提取2-11位	32
            else if (id.Length == 32 && id.StartsWith("P") && id[11] == '#')
            {
                k1001 = id.Substring(1, 10);
            }

            // 3. 涡轮增压器
            // 前十位全为阿拉伯数字时, 提取第1 - 10位，25
            else if (id.Length == 25 && IsNumber(id, 0, 10))
            {
                k1001 = id.Substring(0, 10);
            }
            // 提取第1-8位	31
            else if (id.Length == 31)
            {
                k1001 = id.Substring(0, 8);
            }
            // 提取第1-10位	33
            else if (id.Length == 33)
            {
                k1001 = id.Substring(0, 10);
            }


            // 4.进气歧管组件
            // 第一位固定值为P时，第十二位固定值为#时，提取2-11位	25
            else if (id.Length == 25 && id.StartsWith("P") && id[11] == '#')
            {
                k1001 = id.Substring(1, 10);
            }
            // 第一位固定值为P时，第十位固定值为#时，提取2-9位	30
            else if (id.Length == 25 && id.StartsWith("P") && id[9] == '#')
            {
                k1001 = id.Substring(1, 8);
            }

            // 5.缸盖 末位固定值为#时，倒数第十二位固定值为P时，提取15-24位
            // 末位固定值为#时，倒数第十二位固定值为P时，提取15-24位	25
            else if (id.Length == 25 && id.EndsWith("#") && id[id.Length - 12] == 'P')
            {
                k1001 = identifier.Substring(14, 10);
            }

            // 6 缸体
            // 末位固定值为#时，倒数第十二位固定值为P时，提取第13-22位	23
            else if (id.Length == 23 && id[id.Length - 1] == 'P')
            {
                k1001 = id.Substring(12, 10);
            }
            // 第十二位固定值为P时，第二十三位固定值为#时提取第13-22位	32
            else if (id.Length == 32 && id[22] == 'P')
            {
                k1001 = id.Substring(12, 10);
            }

            return k1001;
        }

        /// <summary>
        /// 判断指定字符串s，从 start 开始的连续 len 个字符是否是数字。
        /// </summary>
        /// <param name="id"></param>
        /// <param name="start"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        private bool IsNumber(string id, int start, int len)
        {
            bool isNumber = true;
            for (int i = 0; i < len; i++)
            {
                if (!char.IsDigit(id[start + i]))
                    isNumber = false;
            }
            return isNumber;
        }


        /// <summary>
        /// 整个查询字符串。
        /// 2019-3-15 加入查询 Result.PositionID 和 vUnitProgramBolt.UnitName
        /// </summary>
        /// <returns></returns>
        private string GetSql()
        {
            string sqltemplate =
@"SELECT TOP {count}
	ResultTightening.ResultID, 
	ResultTightening.FinalAngle, 
	ResultTightening.FinalTorque, 
	Result.ResultDateTime, 
	Result.ProgramID, 
	ResultIdentifier.Identifier,
    'UnitName' as UnitName, -- vUnitProgramBolt.UnitName,
    'BoltName' as BoltName,--vUnitProgramBolt.BoltName,
    'SystemType' as SystemType,--vUnitProgramBolt.SystemType,
    ProgramParameter.ParameterValue,
    ProgramParameter.LimitHigh,
    ProgramParameter.LimitLow,
    Result.PositionID,
    'ProgramName' as UnitName, --vUnitProgramBolt.ProgramName,
    ResultStep.ResultStepID
FROM 
	ACDC.Result INNER JOIN
	ACDC.ResultTightening ON ACDC.Result.ID = ACDC.ResultTightening.ResultID INNER JOIN
	-- vUnitProgramBolt ON ACDC.Result.ID = vUnitProgramBolt.ResultId INNER JOIN
	ACDC.ResultToResultIdentifier ON ACDC.ResultToResultIdentifier.ResultID = ACDC.Result.ID INNER JOIN
	ACDC.ResultIdentifier ON ACDC.ResultToResultIdentifier.ResultIdentifierID = ACDC.ResultIdentifier.ID INNER JOIN
	ACDC.ProgramParameter ON ACDC.Result.ProgramID = ACDC.ProgramParameter.ProgramID LEFT OUTER JOIN
    ACDC.ResultStep ON ACDC.Result.ID = ACDC.ResultStep.ResultID
WHERE 
	ACDC.ProgramParameter.ProgramParameterTypeID in (1,2) and {condition}
ORDER BY
	ACDC.ResultTightening.ResultID";
            string condition1 = $"ACDC.Result.ResultDateTime >= '{startDate}'";
            string condition2 = $"ACDC.ResultTightening.ResultID >= {LastResID}";
            string sql = sqltemplate.Replace("{count}", BatchCount.ToString());
            return sql.Replace("{condition}", LastResID == 0 ? condition1 : condition2);
        }


        private void prepareDictionaries()
        {
            /*************************************************************************************************
             *  Program Parameter Data
             *  0.ID	1.ProgramID	2.ProgramParameterTypeID	3.ParameterValue	4.LimitHigh	5.LimitLow
             *  e.g.  1   1   1   NULL    27  23
             **************************************************************************************************/
            sm.CommandText = "select * from ProgramParameter";
            string[][] pps = sm.GetStrings(); // PPS is ProgramParameter. 

            programParamters.Clear();
            for (int i = 0; i < pps.Length; i++)
                programParamters.Add(pps[i][1] + "_" + pps[i][2], pps[i]);

            /*************************************************************************************************
             *  Result Step Data
             *  0.ResultID, 1.ResultStepID. 
             **************************************************************************************************/
            sm.CommandText = "select ResultID, ResultStepID from ResultStep";
            string[][] rss = sm.GetStrings();
            //AddLog("DEBUG", "rss.count = " + rss.Length);

            rsdic.Clear();
            for (int i = 0; i < rss.Length; i++)
                if (!rsdic.Keys.Contains(rss[i][0]))
                    rsdic.Add(rss[i][0], rss[i][1]);
        }

        private QCharacteristic GetCharacteristic(QFile qf, string k2001, string k2002)
        {
            // 找到K2001和K2002相同的参数。
            QCharacteristic q = qf.Charactericstics.Find(
                qc => qc[2001].ToString() == k2001 && qc[2002].ToString() == k2002);

            // 如果没找到则用K2001和K2002初始化一个新的参数。
            if (q == null)
            {
                q = new QCharacteristic();
                q[2001] = k2001;
                q[2002] = k2002;
                qf.Charactericstics.Add(q);
            }

            return q;
        }

    }
}

